#include "pr2000_support.h"

#if defined(__HOST_LINUX_SYSTEM__)
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/miscdevice.h>
#include <linux/proc_fs.h>
#include <linux/kthread.h>
#include <linux/freezer.h>

#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/system.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/string.h>
#include <linux/list.h>
#include <asm/delay.h>
#include <linux/timer.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>
#include <linux/poll.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <linux/moduleparam.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>

#include <linux/i2c.h>

#include "../camera.h"


#elif defined(__HOST_MICOM_SYSTEM__)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#if defined(STM32F10X_HD)
#include "stm32f10x.h"
#else
//#include "stm8s.h"
#endif

#include "i51_i2c_gpio.h"

//#include "uart.h"
//#include "delay.h"
//#include "user_func.h"

#endif // __HOST_LINUX_SYSTEM__

#include "pr2000.h"
#include "pr2000_table.h"
#include "pr2000_func.h"
#include "pr2000_ceqfunc.h"
#include "pr2000_user_config.h"

int PR2000_SetTableCommon(const int i2cFd, const uint8_t slvAddr);
int PR2000_SetTableIRQ(const int i2cFd, const uint8_t slvAddr);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#if defined(__HOST_LINUX_SYSTEM__)

#if defined(I2C_INTF_ALLWINNER) /* AllWinner i2c driver */
////////////////////////////////////////
/*** use AllWinner i2c interface function ***/
////////////////////////////////////////

extern 	void *g_pV4l2_subdev;

static int pr2000_i2c_read(uint8_t i2cSlvAddr, void *buf, u8 addr, size_t size) 
{
	int i = 0;

	if (g_pV4l2_subdev == NULL)
	{
		return 0;
	}
	
	for (i = 0; i < size; i++)
	{
		cci_read_a8_d8(g_pV4l2_subdev, addr+i, &buf[i]);
	}
	return size; 
}

/* write value to register */
static int pr2000_i2c_write(uint8_t i2cSlvAddr, uint8_t *buf, u8 addr, size_t size)
{       
	int i = 0;

	if (g_pV4l2_subdev == NULL)
	{
		return 0;
	}
	
	for (i = 0; i < size; i++)
	{
		cci_write_a8_d8(g_pV4l2_subdev, addr+i, buf[i]);
	}
	return size; 
}

int PR2000_SetPage(const int fd, const uint8_t slvAddr, int page)
{
	int ret = 0;

	/*TODO call i2c adapter function */
	/* 
	 * exam> 
	 * 	I2C_Write(slvAddr, 0xFF, page)
	 *
	 */

	uint8_t i2cBuf[2];

	i2cBuf[0] = 0xFF; 		//addr
	i2cBuf[1] = (uint8_t)page;	//data
	ret = pr2000_i2c_write(slvAddr, &i2cBuf[1], i2cBuf[0], sizeof(uint8_t));

	return(ret);
}

int PR2000_Read(const int fd, const uint8_t slvAddr, const uint8_t addr, uint8_t *pData)
{
	int ret = 0;

	/*TODO call i2c adapter function */
	/* 
	 * exam> 
	 * 	*pData = I2C_Read(slvAddr, addr)
	 *
	 */
	uint8_t i2cBuf[1];

	ret = pr2000_i2c_read(slvAddr, i2cBuf, addr, sizeof(uint8_t));

	*pData = i2cBuf[0];

	return(ret);
}

int PR2000_Write(const int fd, const uint8_t slvAddr, const uint8_t addr, uint8_t data)
{
	int ret = 0;

	ret = pr2000_i2c_write(slvAddr, &data, addr, sizeof(uint8_t));
	return(ret);
}

int PR2000_PageRead(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, uint8_t *pData)
{
	int ret = 0;

	/*TODO call i2c adapter function */
	/* 
	 * exam> 
	 * 	I2C_Write(slvAddr, 0xFF, page)
	 * 	*pData = I2C_Read(slvAddr, addr)
	 *
	 */
	uint8_t i2cBuf[2];

	i2cBuf[0] = 0xFF; 		//addr
	i2cBuf[1] = (uint8_t)page;	//data
	ret = pr2000_i2c_write(slvAddr, &i2cBuf[1], i2cBuf[0],  sizeof(uint8_t));

	ret = pr2000_i2c_read(slvAddr, i2cBuf, addr, sizeof(uint8_t));

	*pData = i2cBuf[0];
	return(ret);
}

int PR2000_PageWrite(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, uint8_t data)
{
	int ret = 0;

	/*TODO call i2c adapter function */
	/* 
	 * exam> 
	 * 	I2C_Write(slvAddr, 0xFF, page)
	 * 	I2C_Write(slvAddr, addr, data)
	 *
	 */
	uint8_t i2cBuf[2];

	i2cBuf[0] = 0xFF; 		//addr
	i2cBuf[1] = (uint8_t)page;	//data
	ret = pr2000_i2c_write(slvAddr, &i2cBuf[1], i2cBuf[0], sizeof(uint8_t));

	i2cBuf[0] = addr; 		//addr
	i2cBuf[1] = data;		//data
	ret = pr2000_i2c_write(slvAddr, &i2cBuf[1], addr, sizeof(uint8_t));
	return(ret);
}

int PR2000_PageReadMaskBit(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, const uint8_t maskBit, uint8_t *pData)
{
	int ret = 0;

	/*TODO call i2c adapter function */
	/* 
	 * exam> 
	 * 	I2C_Write(slvAddr, 0xFF, page)
	 * 	tmp = I2C_Read(slvAddr, addr)
	 * 	*pData = tmp & (maskBit)
	 *
	 */
	uint8_t i2cBuf[2];

	i2cBuf[0] = 0xFF; 		//addr
	i2cBuf[1] = (uint8_t)page;	//data
	ret = pr2000_i2c_write(slvAddr, &i2cBuf[1], i2cBuf[0], sizeof(uint8_t));

	ret = pr2000_i2c_read(slvAddr, i2cBuf, addr, sizeof(uint8_t));

	*pData = i2cBuf[0] & (~maskBit);
	return(ret);
}

int PR2000_PageWriteMaskBit(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, const uint8_t maskBit, const uint8_t data)
{
	int ret = 0;

	/*TODO call i2c adapter function */
	/* 
	 * exam> 
	 * 	I2C_Write(slvAddr, 0xFF, page)
	 * 	tmp = I2C_Read(slvAddr, addr)
	 * 	tmp = (tmp & (~maskBit)) | (data & maskBit)
	 * 	I2C_Write(slvAddr, addr, tmp)
	 *
	 */
	uint8_t i2cBuf[2];
	uint8_t tmp;

	i2cBuf[0] = 0xFF; 		//addr
	i2cBuf[1] = (uint8_t)page;	//data
	ret = pr2000_i2c_write(slvAddr, &i2cBuf[1], i2cBuf[0], sizeof(uint8_t));

	ret = pr2000_i2c_read(slvAddr, i2cBuf, addr, sizeof(uint8_t));

	tmp = (i2cBuf[0] & (~maskBit)) | (data & maskBit);

	i2cBuf[0] = addr; 		//addr
	i2cBuf[1] = tmp;		//data
	ret = pr2000_i2c_write(slvAddr, &i2cBuf[1], addr, sizeof(uint8_t));
	return(ret);
}

int PR2000_PageReadBurst(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, const uint8_t length, uint8_t *pData)
{
	int ret = 0;

	/*TODO call i2c adapter function */
	/* 
	 * exam> 
	 * 	I2C_Write(slvAddr, 0xFF, page)
	 * 	for(i=0; i<lenght; i++) pData[i] = I2C_Read(slvAddr, addr) <<-- "don't increase addr"
	 *
	 */
	uint8_t i2cBuf[2];

	i2cBuf[0] = 0xFF; 		//addr
	i2cBuf[1] = (uint8_t)page;	//data
	ret = pr2000_i2c_write(slvAddr, &i2cBuf[1], i2cBuf[0], sizeof(uint8_t));

	ret = pr2000_i2c_read(slvAddr, pData, addr, length);
	return(ret);
}

int PR2000_PageWriteBurst(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, const uint8_t length, uint8_t *pData)
{
	int ret = 0;

	/*TODO call i2c adapter function */
	/* 
	 * exam> 
	 * 	I2C_Write(slvAddr, 0xFF, page)
	 * 	for(i=0; i<lenght; i++) I2C_Write(slvAddr, addr, pData[i])  <<-- "don't increase addr"
	 *
	 */
	uint8_t i2cBuf[2];
	uint8_t *pBuf;

	i2cBuf[0] = 0xFF; 		//addr
	i2cBuf[1] = (uint8_t)page;	//data
	ret = pr2000_i2c_write(slvAddr, &i2cBuf[1], i2cBuf[0], sizeof(uint8_t));

	pBuf = kzalloc((length +1), GFP_KERNEL);
	if(!pBuf) return(-1);

	memcpy(&pBuf[1], pData, length);
	pBuf[0] = addr;
	ret = pr2000_i2c_write(slvAddr, &pBuf[1], addr, length+1);

	kfree(pBuf);
	return(ret);
}

#elif defined(I2C_INTF_LINUX_ADAPTER_DRIVER) /* linux native i2c adapter drvier */
////////////////////////////////////////
/*** use linux i2c interface function ***/ //---> not yet tested
////////////////////////////////////////
#if 0
extern _pr2000_i2c_data *gpPr2000_i2c_data;

static DEFINE_MUTEX(pr2000_i2c_mutex);
static int pr2000_i2c_read(uint8_t i2cSlvAddr, void *buf, u8 addr, size_t size) 
{
        struct i2c_msg msg[2];
        int ret; 

        msg[0].addr = i2cSlvAddr;
        msg[0].flags = 0; 
        msg[0].buf = &addr;
        msg[0].len = sizeof(addr);
        msg[1].addr = i2cSlvAddr;
        msg[1].flags = I2C_M_RD;
        msg[1].buf = buf;
        msg[1].len = size; //size of buf

        mutex_lock(&pr2000_i2c_mutex);
        ret = i2c_transfer(gpPr2000_i2c_data->pr2000_i2c_client->adapter, msg, ARRAY_SIZE(msg));
        mutex_unlock(&pr2000_i2c_mutex);

        if (ret < 0) 
                return ret; 

        return size; 
}

/* write value to register */
static int pr2000_i2c_write(uint8_t i2cSlvAddr, void *buf, size_t size)
{       
        struct i2c_msg msg[1];
        int ret;
        
        msg[0].addr = i2cSlvAddr;
        msg[0].flags = 0;
        msg[0].buf = buf;
        msg[0].len = size; //size of buf
        
        mutex_lock(&pr2000_i2c_mutex);
        ret = i2c_transfer(gpPr2000_i2c_data->pr2000_i2c_client->adapter, msg, ARRAY_SIZE(msg));
        mutex_unlock(&pr2000_i2c_mutex);
        
        /* i2c_transfer returns number of messages transferred */
        if (ret < 0)
                return ret;
        
        return(size);
}

int PR2000_SetPage(const int fd, const uint8_t slvAddr, int page)
{
	int ret = 0;

	uint8_t i2cBuf[2];

	i2cBuf[0] = 0xFF; 		//addr
	i2cBuf[1] = (uint8_t)page;	//data
	ret = pr2000_i2c_write(slvAddr, i2cBuf, sizeof(uint8_t)*2);

	return(ret);
}

int PR2000_Read(const int fd, const uint8_t slvAddr, const uint8_t addr, uint8_t *pData)
{
	int ret = 0;

	uint8_t i2cBuf[1];

	ret = pr2000_i2c_read(slvAddr, i2cBuf, addr, sizeof(uint8_t));

	*pData = i2cBuf[0];

	return(ret);
}

int PR2000_Write(const int fd, const uint8_t slvAddr, const uint8_t addr, uint8_t data)
{
	int ret = 0;

	uint8_t i2cBuf[2];

	i2cBuf[0] = addr; 		//addr
	i2cBuf[1] = data;		//data
	ret = pr2000_i2c_write(slvAddr, i2cBuf, sizeof(uint8_t)*2);

	return(ret);
}

int PR2000_PageRead(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, uint8_t *pData)
{
	int ret = 0;

	uint8_t i2cBuf[2];

	i2cBuf[0] = 0xFF; 		//addr
	i2cBuf[1] = (uint8_t)page;	//data
	ret = pr2000_i2c_write(slvAddr, i2cBuf, sizeof(uint8_t)*2);

	ret = pr2000_i2c_read(slvAddr, i2cBuf, addr, sizeof(uint8_t));

	*pData = i2cBuf[0];

	return(ret);
}

int PR2000_PageWrite(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, uint8_t data)
{
	int ret = 0;

	uint8_t i2cBuf[2];

	i2cBuf[0] = 0xFF; 		//addr
	i2cBuf[1] = (uint8_t)page;	//data
	ret = pr2000_i2c_write(slvAddr, i2cBuf, sizeof(uint8_t)*2);

	i2cBuf[0] = addr; 		//addr
	i2cBuf[1] = data;		//data
	ret = pr2000_i2c_write(slvAddr, i2cBuf, sizeof(uint8_t)*2);

	return(ret);
}

int PR2000_PageReadMaskBit(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, const uint8_t maskBit, uint8_t *pData)
{
	int ret = 0;

	uint8_t i2cBuf[2];

	i2cBuf[0] = 0xFF; 		//addr
	i2cBuf[1] = (uint8_t)page;	//data
	ret = pr2000_i2c_write(slvAddr, i2cBuf, sizeof(uint8_t)*2);

	ret = pr2000_i2c_read(slvAddr, i2cBuf, addr, sizeof(uint8_t));

	*pData = i2cBuf[0] & (~maskBit);

	return(ret);
}

int PR2000_PageWriteMaskBit(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, const uint8_t maskBit, const uint8_t data)
{
	int ret = 0;

	uint8_t i2cBuf[2];
	uint8_t tmp;

	i2cBuf[0] = 0xFF; 		//addr
	i2cBuf[1] = (uint8_t)page;	//data
	ret = pr2000_i2c_write(slvAddr, i2cBuf, sizeof(uint8_t)*2);

	ret = pr2000_i2c_read(slvAddr, i2cBuf, addr, sizeof(uint8_t));

	tmp = (i2cBuf[0] & (~maskBit)) | (data & maskBit);

	i2cBuf[0] = addr; 		//addr
	i2cBuf[1] = tmp;		//data
	ret = pr2000_i2c_write(slvAddr, i2cBuf, sizeof(uint8_t)*2);

	return(ret);
}

int PR2000_PageReadBurst(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, const uint8_t length, uint8_t *pData)
{
	int ret = 0;

	uint8_t i2cBuf[2];

	i2cBuf[0] = 0xFF; 		//addr
	i2cBuf[1] = (uint8_t)page;	//data
	ret = pr2000_i2c_write(slvAddr, i2cBuf, sizeof(uint8_t)*2);

	ret = pr2000_i2c_read(slvAddr, pData, addr, length);

	return(ret);
}

int PR2000_PageWriteBurst(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, const uint8_t length, uint8_t *pData)
{
	int ret = 0;

	uint8_t i2cBuf[2];
	uint8_t *pBuf;

	i2cBuf[0] = 0xFF; 		//addr
	i2cBuf[1] = (uint8_t)page;	//data
	ret = pr2000_i2c_write(slvAddr, i2cBuf, sizeof(uint8_t)*2);

	pBuf = kzalloc((length +1), GFP_KERNEL);
	if(!pBuf) return(-1);

	memcpy(&pBuf[1], pData, length);
	pBuf[0] = addr;
	ret = pr2000_i2c_write(slvAddr, pBuf, length+1);

	kfree(pBuf);


	return(ret);
}

#endif

#elif defined(I2C_INTF_HISILLICON) /* Hisillicon i2c drvier */
////////////////////////////////////////
/*** use Hisilicon SOC i2c driver ***/
////////////////////////////////////////
#if 0
extern int PR2000_GPIOI2C_SetPage(const int fd, const uint8_t slvAddr, int page);
extern int PR2000_GPIOI2C_Read(const int fd, const uint8_t slvAddr, const uint8_t addr, uint8_t *pData);
extern int PR2000_GPIOI2C_Write(const int fd, const uint8_t slvAddr, const uint8_t addr, uint8_t data);
extern int PR2000_GPIOI2C_PageRead(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, uint8_t *pData);
extern int PR2000_GPIOI2C_PageWrite(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, uint8_t data);
extern int PR2000_GPIOI2C_PageReadMaskBit(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, const uint8_t maskBit, uint8_t *pData);
extern int PR2000_GPIOI2C_PageWriteMaskBit(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, const uint8_t maskBit, const uint8_t data);
extern int PR2000_GPIOI2C_PageReadBurst(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, const uint8_t length, uint8_t *pData);
extern int PR2000_GPIOI2C_PageWriteBurst(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, const uint8_t length, uint8_t *pData);

int PR2000_SetPage(const int fd, const uint8_t slvAddr, int page)
{
	int ret = 0;

	// call gpio_i2c_8b_pxps/gpio_i2c.c funcion
	ret = PR2000_GPIOI2C_SetPage(fd, slvAddr, page);

#ifdef SUPPORT_REG_SAVEDUMP //support pr2000 register save dump.
	{
		int i;
		for(i = 0; i < gFindPr2000SlvAddrCnt; i++)
		{
			if(gpRegSaveDump[i])
			{
				if(gpRegSaveDump[i]->i2cSlvAddr == slvAddr)
				{
					gpRegSaveDump[i]->curPage = page;
					break;
				}
			}
		}
	}
#endif // SUPPORT_REG_SAVEDUMP //support pr2000 register save dump.


	return(ret);
}
int PR2000_Read(const int fd, const uint8_t slvAddr, const uint8_t addr, uint8_t *pData)
{
	int ret = 0;

	// call gpio_i2c_8b_pxps/gpio_i2c.c funcion
	ret = PR2000_GPIOI2C_Read(fd, slvAddr, addr, pData);

	return(ret);
}
int PR2000_Write(const int fd, const uint8_t slvAddr, const uint8_t addr, uint8_t data)
{
	int ret = 0;

	// call gpio_i2c_8b_pxps/gpio_i2c.c funcion
	ret = PR2000_GPIOI2C_Write(fd, slvAddr, addr, data);

#ifdef SUPPORT_REG_SAVEDUMP //support pr2000 register save dump.
	{
		int i;
		for(i = 0; i < gFindPr2000SlvAddrCnt; i++)
		{
			if(gpRegSaveDump[i])
			{
				if(gpRegSaveDump[i]->i2cSlvAddr == slvAddr)
				{
					if(gpRegSaveDump[i]->curPage < 4)
					{
						gpRegSaveDump[i]->regTbl[gpRegSaveDump[i]->curPage][addr].stReg.b.page = gpRegSaveDump[i]->curPage;
						gpRegSaveDump[i]->regTbl[gpRegSaveDump[i]->curPage][addr].stReg.b.addr = addr;
						gpRegSaveDump[i]->regTbl[gpRegSaveDump[i]->curPage][addr].u8Data = data;
					}
					break;
				}
			}
		}
	}
#endif // SUPPORT_REG_SAVEDUMP //support pr2000 register save dump.


	return(ret);
}
int PR2000_PageRead(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, uint8_t *pData)
{
	int ret = 0;

	// call gpio_i2c_8b_pxps/gpio_i2c.c funcion
	ret = PR2000_GPIOI2C_PageRead(fd, slvAddr, page, addr, pData);

	return(ret);
}
int PR2000_PageWrite(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, uint8_t data)
{
	int ret = 0;

	// call gpio_i2c_8b_pxps/gpio_i2c.c funcion
	ret = PR2000_GPIOI2C_PageWrite(fd, slvAddr, page, addr, data);

#ifdef SUPPORT_REG_SAVEDUMP //support pr2000 register save dump.
	{
		int i;
		for(i = 0; i < gFindPr2000SlvAddrCnt; i++)
		{
			if(gpRegSaveDump[i])
			{
				if(gpRegSaveDump[i]->i2cSlvAddr == slvAddr)
				{
					gpRegSaveDump[i]->curPage = (uint8_t)page;
					if(gpRegSaveDump[i]->curPage < 4)
					{
						gpRegSaveDump[i]->regTbl[gpRegSaveDump[i]->curPage][addr].stReg.b.page = gpRegSaveDump[i]->curPage;
						gpRegSaveDump[i]->regTbl[gpRegSaveDump[i]->curPage][addr].stReg.b.addr = addr;
						gpRegSaveDump[i]->regTbl[gpRegSaveDump[i]->curPage][addr].u8Data = data;

					}
					break;
				}
			}
		}
	}
#endif // SUPPORT_REG_SAVEDUMP //support pr2000 register save dump.


	return(ret);
}
int PR2000_PageReadMaskBit(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, const uint8_t maskBit, uint8_t *pData)
{
	int ret = 0;

	// call gpio_i2c_8b_pxps/gpio_i2c.c funcion
	ret = PR2000_GPIOI2C_PageReadMaskBit(fd, slvAddr, page, addr, maskBit, pData);

	return(ret);
}
int PR2000_PageWriteMaskBit(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, const uint8_t maskBit, const uint8_t data)
{
	int ret = 0;

	// call gpio_i2c_8b_pxps/gpio_i2c.c funcion
	ret = PR2000_GPIOI2C_PageWriteMaskBit(fd, slvAddr, page, addr, maskBit, data);

#ifdef SUPPORT_REG_SAVEDUMP //support pr2000 register save dump.
	{
		int i;

		uint8_t u8RegData = 0;

		if(page >= 0)
		{
			PR2000_GPIOI2C_SetPage(fd, slvAddr, page);
		}

		PR2000_GPIOI2C_Read(fd, slvAddr, addr, &u8RegData);

		u8RegData &= ~(maskBit);

		u8RegData |= (maskBit & data);

		for(i = 0; i < gFindPr2000SlvAddrCnt; i++)
		{
			if(gpRegSaveDump[i])
			{
				if(gpRegSaveDump[i]->i2cSlvAddr == slvAddr)
				{
					gpRegSaveDump[i]->curPage = (uint8_t)page;
					if(gpRegSaveDump[i]->curPage < 4)
					{
						gpRegSaveDump[i]->regTbl[gpRegSaveDump[i]->curPage][addr].stReg.b.page = gpRegSaveDump[i]->curPage;
						gpRegSaveDump[i]->regTbl[gpRegSaveDump[i]->curPage][addr].stReg.b.addr = addr;
						gpRegSaveDump[i]->regTbl[gpRegSaveDump[i]->curPage][addr].u8Data = u8RegData;
					}
					break;
				}
			}
		}
	}
#endif // SUPPORT_REG_SAVEDUMP //support pr2000 register save dump.

	return(ret);
}
int PR2000_PageReadBurst(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, const uint8_t length, uint8_t *pData)
{
	int ret = 0;

	// call gpio_i2c_8b_pxps/gpio_i2c.c funcion
	ret = PR2000_GPIOI2C_PageReadBurst(fd, slvAddr, page, addr, length, pData);

	return(ret);
}
int PR2000_PageWriteBurst(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, const uint8_t length, uint8_t *pData)
{
	int ret = 0;

	// call gpio_i2c_8b_pxps/gpio_i2c.c funcion
	ret = PR2000_GPIOI2C_PageWriteBurst(fd, slvAddr, page, addr, length, pData);

	return(ret);
}
#endif
#endif //defined(I2C_INTF_HISILLICON) /* linux native i2c adapter drvier */

#elif defined(__HOST_MICOM_SYSTEM__)

#if 0
#define I2C_Write io_I2C_Write
#define I2C_Read io_I2C_Read
#define I2C_ReadBurst io_I2C_ReadBurst
#define I2C_WriteBurst io_I2C_WriteBurst

/*** PR2000 I2C Funcion ***/
volatile int spinLockI2C = 0;
int PR2000_SetPage(const int fd, const uint8_t slvAddr, int page)
{
	int ret = 0;

	while(spinLockI2C==1); spinLockI2C = 1;

	ret = I2C_Write(slvAddr, 0xFF, (uint8_t)page);

#ifdef SUPPORT_REG_SAVEDUMP //support pr2000 register save dump.
	{
		int i;
		for(i = 0; i < gFindPr2000SlvAddrCnt; i++)
		{
			if(gpRegSaveDump[i])
			{
				if(gpRegSaveDump[i]->i2cSlvAddr == slvAddr)
				{
					gpRegSaveDump[i]->curPage = page;
					break;
				}
			}
		}
	}
#endif // SUPPORT_REG_SAVEDUMP //support pr2000 register save dump.

	spinLockI2C = 0;
	return(ret);
}


int PR2000_Read(const int fd, const uint8_t slvAddr, const uint8_t addr, uint8_t *pData)
{
	int ret = 0;

	while(spinLockI2C==1); spinLockI2C = 1;

	pData[0] ^= 0xFF; //init
	*pData = I2C_Read(slvAddr, addr);

	spinLockI2C = 0;
	return(ret);
}

int PR2000_Write(const int fd, const uint8_t slvAddr, const uint8_t addr, uint8_t Data)
{
	int ret = 0;

	while(spinLockI2C==1); spinLockI2C = 1;

	ret = I2C_Write(slvAddr, addr, Data);

#ifdef SUPPORT_REG_SAVEDUMP //support pr2000 register save dump.
	{
		int i;
		for(i = 0; i < gFindPr2000SlvAddrCnt; i++)
		{
			if(gpRegSaveDump[i])
			{
				if(gpRegSaveDump[i]->i2cSlvAddr == slvAddr)
				{
					if(gpRegSaveDump[i]->curPage < 4)
					{
						gpRegSaveDump[i]->regTbl[gpRegSaveDump[i]->curPage][addr].stReg.b.page = gpRegSaveDump[i]->curPage;
						gpRegSaveDump[i]->regTbl[gpRegSaveDump[i]->curPage][addr].stReg.b.addr = addr;
						gpRegSaveDump[i]->regTbl[gpRegSaveDump[i]->curPage][addr].u8Data = Data;
					}
					break;
				}
			}
		}
	}
#endif // SUPPORT_REG_SAVEDUMP //support pr2000 register save dump.

	spinLockI2C = 0;
	return(ret);
}

int PR2000_PageRead(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, uint8_t *pData)
{
	int ret = 0;

	while(spinLockI2C==1); spinLockI2C = 1;

	if(pData == NULL) return(-1);
	pData[0] ^= 0xFF; //init

	if(page >= 0)
	{
		I2C_Write(slvAddr, 0xFF, (uint8_t)page);
	}

	*pData = I2C_Read(slvAddr, addr);

	spinLockI2C = 0;
	return(ret);
}

int PR2000_PageWrite(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, uint8_t Data)
{
	int ret = 0;

	while(spinLockI2C==1); spinLockI2C = 1;

	if(page >= 0)
	{
		I2C_Write(slvAddr, 0xFF, (uint8_t)page);
	}

	ret = I2C_Write(slvAddr, addr, Data);

#ifdef SUPPORT_REG_SAVEDUMP //support pr2000 register save dump.
	{
		int i;
		for(i = 0; i < gFindPr2000SlvAddrCnt; i++)
		{
			if(gpRegSaveDump[i])
			{
				if(gpRegSaveDump[i]->i2cSlvAddr == slvAddr)
				{
					gpRegSaveDump[i]->curPage = (uint8_t)page;
					if(gpRegSaveDump[i]->curPage < 4)
					{
						gpRegSaveDump[i]->regTbl[gpRegSaveDump[i]->curPage][addr].stReg.b.page = gpRegSaveDump[i]->curPage;
						gpRegSaveDump[i]->regTbl[gpRegSaveDump[i]->curPage][addr].stReg.b.addr = addr;
						gpRegSaveDump[i]->regTbl[gpRegSaveDump[i]->curPage][addr].u8Data = Data;

					}
					break;
				}
			}
		}
	}
#endif // SUPPORT_REG_SAVEDUMP //support pr2000 register save dump.

	spinLockI2C = 0;
	return(ret);
}

int PR2000_PageReadMaskBit(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, const uint8_t maskBit, uint8_t *pData)
{
	int ret = 0;
	uint8_t u8RegData = 0;

	while(spinLockI2C==1); spinLockI2C = 1;

	if(pData == NULL) 
	{
		spinLockI2C = 0;
		return(-1);
	}
	pData[0] ^= 0xFF; //init

	if(page >= 0)
	{
		I2C_Write(slvAddr, 0xFF, (uint8_t)page);
	}

	u8RegData = I2C_Read(slvAddr, addr);

	u8RegData &= maskBit;

	*pData = u8RegData;

	spinLockI2C = 0;
	return(ret);
}

int PR2000_PageWriteMaskBit(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, const uint8_t maskBit, const uint8_t Data)
{
	int ret = 0;
	uint8_t u8RegData = 0;

	while(spinLockI2C==1); spinLockI2C = 1;

	if(page >= 0)
	{
		I2C_Write(slvAddr, 0xFF, (uint8_t)page);
	}

	u8RegData = I2C_Read(slvAddr, addr);

	u8RegData &= ~(maskBit);

	u8RegData |= (maskBit & Data);

	ret = I2C_Write(slvAddr, addr, u8RegData);

#ifdef SUPPORT_REG_SAVEDUMP //support pr2000 register save dump.
	{
		int i;
		for(i = 0; i < gFindPr2000SlvAddrCnt; i++)
		{
			if(gpRegSaveDump[i])
			{
				if(gpRegSaveDump[i]->i2cSlvAddr == slvAddr)
				{
					gpRegSaveDump[i]->curPage = (uint8_t)page;
					if(gpRegSaveDump[i]->curPage < 4)
					{
						gpRegSaveDump[i]->regTbl[gpRegSaveDump[i]->curPage][addr].stReg.b.page = gpRegSaveDump[i]->curPage;
						gpRegSaveDump[i]->regTbl[gpRegSaveDump[i]->curPage][addr].stReg.b.addr = addr;
						gpRegSaveDump[i]->regTbl[gpRegSaveDump[i]->curPage][addr].u8Data = u8RegData;
					}
					break;
				}
			}
		}
	}
#endif // SUPPORT_REG_SAVEDUMP //support pr2000 register save dump.


	spinLockI2C = 0;
	return(ret);
}

int PR2000_PageReadBurst(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, const uint8_t length, uint8_t *pData)
{
	int ret = 0;

	if(pData == NULL) 
	{
		spinLockI2C = 0;
		return(-1);
	}
	pData[0] ^= 0xFF; //init

	if(page >= 0)
	{
		I2C_Write(slvAddr, 0xFF, (uint8_t)page);
	}

	if( (ret = I2C_ReadBurst(slvAddr, addr, length, pData)) < 0)
	{
		spinLockI2C = 0;
		return(-1);
	}

	spinLockI2C = 0;
	return(ret);
}

int PR2000_PageWriteBurst(const int fd, const uint8_t slvAddr, const int page, const uint8_t addr, const uint8_t length, uint8_t *pData)
{
	int ret = 0;

	while(spinLockI2C==1); spinLockI2C = 1;

	if(pData == NULL) 
	{
		spinLockI2C = 0;
		return(-1);
	}

	if(page >= 0)
	{
		I2C_Write(slvAddr, 0xFF, (uint8_t)page);
	}

	ret = I2C_WriteBurst(slvAddr, addr, length, pData);

	spinLockI2C = 0;
	return(ret);
}
#endif

#endif //defined(__HOST_LINUX_SYSTEM__)

/*******************/
static int PR2000_CheckI2CReadWrite(const int i2cFd, const uint8_t slvAddr)
{
	int result = 0;

	_stPR2000_Reg stReg;
	int i;

	uint8_t u8RegData;
	const uint8_t testRWData[8] = { 0x00, 0xFF, 0xAA, 0x55, 0x0A, 0x50, 0xFA, 0xCE };
	uint8_t u8Temp[8] = {0, };

	/* Check Single Read - Write */
	#if 0
	{
		for(i = 0; i < 8; i++)
		{
			stReg.reg = 0x0070 + i;
			result = PR2000_PageWrite(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, testRWData[i]);
		}
		for(i = 0; i < 8; i++) { u8Temp[i] = 0xFF; }
		for(i = 0; i < 8; i++)
		{
			stReg.reg = 0x0070 + i;
			result = PR2000_PageRead(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, &u8Temp[i]);
		}
		for(i = 0; i < 8; i++)
		{
			if(u8Temp[i] != testRWData[i])
			{
				Error("Invalid data[Wr:0x%02x, Rd:0x%02x]\n", testRWData[i] COMMA u8Temp[i]);
				result = -1;
				break;
			}
		}
	}
	if(result < 0) return(result);
	else PrintString("I2C Single R/W Ok..\n");
	#endif
	
	/* Should do write common registers. */
	PR2000_SetTableCommon(i2cFd, slvAddr);

	/* Check Burst Read - Write */
	#if 0
	{
		stReg.reg = 0x0070;
		result = PR2000_PageWriteBurst(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, 8, (uint8_t *)testRWData);

		for(i = 0; i < 8; i++) { u8Temp[i] = 0xFF; }
		stReg.reg = 0x0070;
		result = PR2000_PageReadBurst(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, 8, u8Temp);

		for(i = 0; i < 8; i++)
		{
			if(u8Temp[i] != testRWData[i])
			{
				Error("Invalid data i:%d[Wr:0x%02x, Rd:0x%02x]\n", i COMMA testRWData[i] COMMA u8Temp[i]);
				result = -1;
				break;
			}
		}
	}
	if(result < 0) return(result);
	else PrintString("I2C Burst R/W Ok..\n");
	#endif
	
    #if 0
	/* Check Burst UTC Tx buffer Read - Write */
	{
		stReg.reg = 0x0220;
		u8RegData = 0x80;
		result = PR2000_PageWrite(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegData);
		stReg.reg = 0x0210;
		u8RegData = 0x80;
		result = PR2000_PageWrite(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegData);
		stReg.reg = 0x020D;
		u8RegData = 0x40;
		result = PR2000_PageWrite(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegData);

		stReg.reg = 0x0211;
		result = PR2000_PageWriteBurst(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, 8, (uint8_t *)testRWData);

		stReg.reg = 0x0212;
		result = PR2000_PageRead(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, &u8RegData);

		if(u8RegData != 8)
		{
			Error("Invalid data[ u8RegData:0x%02x]\n", u8RegData);
			result = -1;
		}

		stReg.reg = 0x0220;
		u8RegData = 0x00;
		PR2000_PageWrite(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegData);
		stReg.reg = 0x0210;
		u8RegData = 0x00;
		PR2000_PageWrite(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegData);

	}
	if(result < 0) return(result);
	else PrintString("I2C Burst UTC Tx buffer R/W Ok..\n");

	/* Check Burst SPI Tx buffer Read - Write */
	{
		stReg.reg = 0x0240;
		u8RegData = 0x80;
		result = PR2000_PageWrite(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegData);
		stReg.reg = 0x0250;
		u8RegData = 0x40;
		result = PR2000_PageWrite(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegData);
		stReg.reg = 0x0251;
		u8RegData = 0x00;
		result = PR2000_PageWrite(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegData);

		stReg.reg = 0x0252;
		result = PR2000_PageWriteBurst(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, 8, (uint8_t *)testRWData);

		stReg.reg = 0x0251;
		result = PR2000_PageRead(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, &u8RegData);

		if(u8RegData != 8)
		{
			Error("Invalid data[ u8RegData:0x%02x]\n", u8RegData);
			result = -1;
		}

	}
	if(result < 0) return(result);
	else PrintString("I2C Burst SPI Tx buffer R/W Ok..\n");

    #endif

	return(result);
}


int PR2000_CheckChipID_SWReset(const int i2cFd, const int maxFindSlvNum, uint8_t *pRetFindSlvAddr, uint16_t *pRetChipID, uint8_t *pRetRevID, int *pRetRWVerify)
{
	uint8_t u8Temp = 0;
	uint32_t chipID[4] = {0, };
	uint8_t u8RevID[4] = {0, };
	_stPR2000_Reg stReg;
	const uint8_t slvAddr[4] = {0x5C<<1, 0x5D<<1, 0x5E<<1, 0x5F<<1};
	int i;
	uint8_t detSlvAddr[4] = {0, };
	uint8_t detSlvAddrCnt = 0;

	if(maxFindSlvNum <= 0) return(-1);
	if( (pRetFindSlvAddr == NULL) || (pRetChipID == NULL) || (pRetRevID == NULL) || (pRetRWVerify == NULL) ) return(-1);

	/* Must do one time. PR2000 latch chip i2c slave address */
	//for(i = 0; i < 4; i++)
	for(i = 0; i < 1; i++)
	{				
		PR2000_PageWrite(i2cFd, slvAddr[i], 0x00, 0xA1, 0xFF); //mpp input
	}
	//for(i = 0; i < 4; i++)
	for(i = 0; i < 1; i++)
	{				
		PR2000_Write(i2cFd, slvAddr[i], 0xFF, 0x80); //load slv addr from strap pin
	}

	//for(i = 0; i < 4; i++)
	for(i = 0; i < 1; i++)
	{
		stReg.reg = PR2000_ADDR_CHIPID_MSB;
		if( (PR2000_PageRead(i2cFd, slvAddr[i], stReg.b.page, stReg.b.addr, (uint8_t *)&u8Temp)) < 0)
		{
			continue;
		}
		else
		{
			chipID[i] = ((uint32_t)u8Temp)<<8;
			stReg.reg = PR2000_ADDR_CHIPID_LSB;
			if( (PR2000_PageRead(i2cFd, slvAddr[i], stReg.b.page, stReg.b.addr, (uint8_t *)&u8Temp)) < 0)
			{
				continue;
			}
			else
			{
				chipID[i] |= (uint32_t)u8Temp;

				stReg.reg = PR2000_ADDR_REVID;
				if( (PR2000_PageRead(i2cFd, slvAddr[i], stReg.b.page, stReg.b.addr, (uint8_t *)&u8RevID[i])) < 0)
				{
					continue;
				}
				else
				{

					Print("PR2000 slvAddr:0x%02x, ChipID:0x%04x RevID:0x%02x... ", slvAddr[i]>>1 COMMA chipID[i] COMMA u8RevID[i]);

					if( (chipID[i]&0xFF00) == 0x2000) 
					{
						detSlvAddr[detSlvAddrCnt++] = slvAddr[i];
						PRINTF("Ok.\n");
					}
					else
					{
						Error("Invalid ChipID(0x%04x)\n", 0x2000);
						continue;
					}
				}
			}
		}
	}

	detSlvAddrCnt = (detSlvAddrCnt >= maxFindSlvNum) ? maxFindSlvNum:detSlvAddrCnt;
	for(i = 0; i < detSlvAddrCnt; i++)
	{
		Print("Check I2C R/W test & SW Reset (SlvAddr:0x%02x)\n", detSlvAddr[i]);

		pRetChipID[i] = chipID[i];
		pRetRevID[i] = u8RevID[i];

		/* check i2c read & write */
		pRetFindSlvAddr[i] = 0x00;
		if( (PR2000_CheckI2CReadWrite(i2cFd, detSlvAddr[i])) >= 0)
		{
			pRetRWVerify[i] = TRUE;
			pRetFindSlvAddr[i] = detSlvAddr[i];
			
			/* sw reset all function. */
			#if 0
			{
				PR2000_PageWrite(i2cFd, detSlvAddr[i], 0x00, 0xF8, 0x7F);
				msleep(100);
				PR2000_PageWrite(i2cFd, detSlvAddr[i], 0x00, 0xF8, 0x00);

			}
			#endif
		}
	}

	return(detSlvAddrCnt);
}

int PR2000_SetTableCommon(const int i2cFd, const uint8_t slvAddr)
{
	int result = -1;
	const _stPR2000_Table_Common *pTblCommon = NULL;
	_stPR2000_Reg stReg;
	int regInx = 0;
	uint8_t u8RegData;

	Print("%02x-Set common register\n", slvAddr);

	pTblCommon = (const _stPR2000_Table_Common *)stPR2000_Table_Common;
	regInx = 0;
	stReg.reg = pTblCommon[regInx].stReg.reg;
	while(stReg.reg != 0xFFFF)
	{
		u8RegData = pTblCommon[regInx].u8Data;
		Dbg("inx:%d, page:%d, reg:0x%02x, data:0x%02x\n", regInx COMMA stReg.b.page COMMA stReg.b.addr COMMA u8RegData);

		if( (result = PR2000_PageWrite(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegData)) < 0)
		{
			ErrorString("invalid page write\n");
			return(result);
		}

		regInx++;
		stReg.reg = pTblCommon[regInx].stReg.reg;
	}


	return(result);
}

int PR2000_SetTableClkPhase(const int i2cFd, const uint8_t slvAddr, const uint8_t dataRate, const uint8_t clkPhaseNum)
{
	int result = -1;
	_stPR2000_Reg stReg;
	uint8_t u8RegData;
	uint8_t u8RegMask;
	const uint8_t *pTblClkPhase = NULL;

	Print("%02x-Set Clock phase num(%d)\n", slvAddr COMMA clkPhaseNum);
	if(dataRate <= 1) 
	{
		if(clkPhaseNum > 15)
		{
			Error("Invalid clkphase:%d\n", clkPhaseNum);
			return(result);
		}
	}
	else if(dataRate <= 3) 
	{
		if(clkPhaseNum > 3)
		{
			Error("Invalid clkphase:%d\n", clkPhaseNum);
			return(result);
		}
	}
	else
	{
		Error("Invalid clkphase:%d\n", clkPhaseNum);
		return(result);
	}

	if(dataRate == 0)
	{
		pTblClkPhase = pr2000_table_148Mhzclk_phase[clkPhaseNum];
	}
	else if(dataRate == 1)
	{
		pTblClkPhase = pr2000_table_74Mhzclk_phase[clkPhaseNum];
	}
	else if(dataRate == 2)
	{
		pTblClkPhase = &pr2000_table_36Mhzclk_phase[clkPhaseNum];
	}
	else
	{
		pTblClkPhase = &pr2000_table_27Mhzclk_phase[clkPhaseNum];
	}


	stReg.reg = 0x00E3;
	u8RegData = pTblClkPhase[0];
	u8RegMask = 0x3F;
	Dbg("page:%d, reg:0x%02x, data:0x%02x\n", stReg.b.page COMMA stReg.b.addr COMMA u8RegData);
	if( (result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData)) < 0)
	{
		ErrorString("invalid page write\n");
		return(result);
	}

	stReg.reg = 0x00E4;
	u8RegData = pTblClkPhase[0];
	u8RegMask = 0x3F;
	Dbg("page:%d, reg:0x%02x, data:0x%02x\n", stReg.b.page COMMA stReg.b.addr COMMA u8RegData);
	if( (result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData)) < 0)
	{
		ErrorString("invalid page write\n");
		return(result);
	}

	if(dataRate <= 1)
	{
		stReg.reg = 0x00E2;
		u8RegData = pTblClkPhase[1];
		u8RegMask = 0x30;
		Dbg("page:%d, reg:0x%02x, data:0x%02x\n", stReg.b.page COMMA stReg.b.addr COMMA u8RegData);
		if( (result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData)) < 0)
		{
			ErrorString("invalid page write\n");
			return(result);
		}

		stReg.reg = 0x00D8;
		u8RegData = pTblClkPhase[2];
		u8RegMask = 0x07;
		Dbg("page:%d, reg:0x%02x, data:0x%02x\n", stReg.b.page COMMA stReg.b.addr COMMA u8RegData);
		if( (result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData)) < 0)
		{
			ErrorString("invalid page write\n");
			return(result);
		}
	}

	return(result);
}


int PR2000_SetAttrChip(const int i2cFd, const uint8_t slvAddr, const _stAttrChip *pstPr2000AttrChip)
{
	int result = -1;
	_stPR2000_Reg stReg;
	uint8_t u8RegData;
	uint8_t u8RegMask;

	Print("%02x-Set Chip attribute register\n", slvAddr);

	/* set chip attribute */
	if(pstPr2000AttrChip->i2cSlvAddr == slvAddr)
	{
		{    
			PrintString("  [ENV] Chip Attribute:\n");
			Print("    I2C SlvAddr7bit(0x%02X)\n", pstPr2000AttrChip->i2cSlvAddr>>1);
			Print("    vinMode(0:[Differential|VinPN], 1:VinP, 3:VinN): %d\n", pstPr2000AttrChip->vinMode);
			Print("    vidOutMode(0:pararllel, 2:mipi_2lane(~HD), 4:mipi_4lane(~FHD): %d\n", pstPr2000AttrChip->vidOutMode);
			Print("    cascade(0:no, 1:cascade): %d\n", pstPr2000AttrChip->bCascade);
			Print("    cascadeMux(If cascade, 0:single(slave), 1:mux(master)): %d\n", pstPr2000AttrChip->bCascadeMux);
			Print("    chid_num(If cascade, 0:master, 1:slave): %d\n", pstPr2000AttrChip->chid_num);
			Print("    bt656(If parallel, 0:bt1120(8bit), 1:bt656(8bit)): %d\n", pstPr2000AttrChip->bBt656);
			Print("    datarate(0:148.5Mhz, 1:74.25Mhz, 2:36Mhz, 3:27Mhz): %d\n", pstPr2000AttrChip->datarate);
			Print("    clkphase_Mux(If parallel & cascadeMux, clkphase:0~15): %d\n", pstPr2000AttrChip->clkphase_Mux);
			Print("    clkphase_148Mhz(If parallel & datarate=0, clkphase:0~15): %d\n", pstPr2000AttrChip->clkphase_148Mhz);
			Print("    clkphase_74Mhz(If parallel & datarate=1, clkphase:0~15): %d\n", pstPr2000AttrChip->clkphase_74Mhz);
			Print("    clkphase_36Mhz(If parallel & datarate=2, clkphase:0~3): %d\n", pstPr2000AttrChip->clkphase_36Mhz);
			Print("    clkphase_27Mhz(If parallel & datarate=3, clkphase:0~3): %d\n", pstPr2000AttrChip->clkphase_27Mhz);
		}            

		//uint8_t vinMode;
		stReg.reg = 0x0014;
		u8RegData = (pstPr2000AttrChip->vinMode & 0x3)<<0;
		u8RegMask = 0x03;
		result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
		//uint8_t vidOutMode;
		if(pstPr2000AttrChip->vidOutMode == 0) //parallel mode
		{
			//uint8_t bCascade;
			if(pstPr2000AttrChip->bCascade==1)
			{
				stReg.reg = 0x00E0;
				u8RegData = 0x20;
				u8RegMask = 0x30;
				result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
			}
			else
			{
				stReg.reg = 0x00E0;
				u8RegData = 0x30;
				u8RegMask = 0x30;
				result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
			}
		}
		else //mipi mode
		{
			/* mipi power down */
			stReg.reg = 0x00E0;
			u8RegData = 0x10;
			u8RegMask = 0x30;
			result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
		}
		//uint8_t bCascadeMux;
		if(pstPr2000AttrChip->bCascadeMux == 1) // master chip
		{
			stReg.reg = 0x00E1;
			u8RegData = 0x06;
			u8RegMask = 0x07;
			result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);

			if(pstPr2000AttrChip->datarate == 0) //if mux & 148Mhz, enable X2 clk.
			{
				stReg.reg = 0x00E2;
				u8RegData = 0x80;
				u8RegMask = 0x80;
				result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
			}
			else
			{
				stReg.reg = 0x00E2;
				u8RegData = 0x00;
				u8RegMask = 0x80;
				result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
			}
		}
		else
		{
			stReg.reg = 0x00E1;
			u8RegData = 0x00;
			u8RegMask = 0x07;
			result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);

			stReg.reg = 0x00E2;
			u8RegData = 0x00;
			u8RegMask = 0x80;
			result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
		}
		//uint8_t chid_num;
		stReg.reg = 0x00E2;
		u8RegData = (pstPr2000AttrChip->chid_num & 0x3)<<0;
		u8RegMask = 0x03;
		result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
		//uint8_t datarate;
		stReg.reg = 0x00E1;
		if(pstPr2000AttrChip->vidOutMode == 4) //mipi 4lane.
		{
			u8RegData = (0 & 0x3)<<4;
		}
		else if(pstPr2000AttrChip->vidOutMode == 2) //mipi 2lane.
		{
			u8RegData = (1 & 0x3)<<4;
		}
		else //parallel mode
		{
			u8RegData = (pstPr2000AttrChip->datarate & 0x3)<<4;
		}
		u8RegMask = 0x30;
		result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
		//uint8_t bBt656;
		stReg.reg = 0x00E1;
		u8RegData = (pstPr2000AttrChip->bBt656 & 0x1)<<7;
		u8RegMask = 0x80;
		result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
		stReg.reg = 0x014F;
		u8RegData = (pstPr2000AttrChip->bBt656 & 0x1)<<5;
		u8RegMask = 0x20;
		result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
		//uint8_t clkphase_148Mhz; 
		if(pstPr2000AttrChip->vidOutMode == 0)  //If parallel, set
		{
			if(pstPr2000AttrChip->datarate == 0) //148.5Mhz
			{
				stReg.reg = 0x00DA;
				u8RegMask = 0x3F;
				u8RegData = 0x21;
				result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);

				if(pstPr2000AttrChip->bCascadeMux == 1)
				{
					Print("%02x-clkphase_Mux:%d\n", slvAddr COMMA pstPr2000AttrChip->clkphase_Mux);
					result = PR2000_SetTableClkPhase(i2cFd, slvAddr, pstPr2000AttrChip->datarate, pstPr2000AttrChip->clkphase_Mux);
				}
				else
				{
					Print("%02x-clkphase_148Mhz:%d\n", slvAddr COMMA pstPr2000AttrChip->clkphase_148Mhz);
					result = PR2000_SetTableClkPhase(i2cFd, slvAddr, pstPr2000AttrChip->datarate, pstPr2000AttrChip->clkphase_148Mhz);
				}
				/* 
				   stReg.reg = 0x00E3;
				   u8RegMask = 0x10;
				   u8RegData = 0x00;
				   result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
				   stReg.reg = 0x00E4;
				   u8RegMask = 0x10;
				   u8RegData = 0x00;
				   result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
				   */


			}
			else if(pstPr2000AttrChip->datarate == 1) //74.25Mhz
			{
				stReg.reg = 0x00DA;
				u8RegMask = 0x3F;
				u8RegData = 0x21;
				result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);

				Print("%02x-clkphase_74Mhz:%d\n", slvAddr COMMA pstPr2000AttrChip->clkphase_74Mhz);
				result = PR2000_SetTableClkPhase(i2cFd, slvAddr, pstPr2000AttrChip->datarate, pstPr2000AttrChip->clkphase_74Mhz);
				/*
				   stReg.reg = 0x00E3;
				   u8RegMask = 0x10;
				   u8RegData = 0x10;
				   result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
				   stReg.reg = 0x00E4;
				   u8RegMask = 0x10;
				   u8RegData = 0x10;
				   result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
				   */
			}
			else if(pstPr2000AttrChip->datarate == 2) //36Mhz
			{
				stReg.reg = 0x00DA;
				u8RegMask = 0x3F;
				u8RegData = 0x20;
				result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);

				Print("%02x-clkphase_36Mhz:%d\n", slvAddr COMMA pstPr2000AttrChip->clkphase_36Mhz);
				result = PR2000_SetTableClkPhase(i2cFd, slvAddr, pstPr2000AttrChip->datarate, pstPr2000AttrChip->clkphase_36Mhz);
				/*
				   stReg.reg = 0x00E3;
				   u8RegMask = 0x10;
				   u8RegData = 0x10;
				   result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
				   stReg.reg = 0x00E4;
				   u8RegMask = 0x10;
				   u8RegData = 0x10;
				   result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
				   */
			}
			else  //27Mhz
			{
				stReg.reg = 0x00DA;
				u8RegMask = 0x3F;
				u8RegData = 0x18;
				result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);

				Print("%02x-clkphase_27Mhz:%d\n", slvAddr COMMA pstPr2000AttrChip->clkphase_27Mhz);
				result = PR2000_SetTableClkPhase(i2cFd, slvAddr, pstPr2000AttrChip->datarate, pstPr2000AttrChip->clkphase_27Mhz);
				/*
				   stReg.reg = 0x00E3;
				   u8RegMask = 0x10;
				   u8RegData = 0x10;
				   result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
				   stReg.reg = 0x00E4;
				   u8RegMask = 0x10;
				   u8RegData = 0x10;
				   result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
				   */
			}

		}
	}
	else
	{
		ErrorString("Invalid i2c slave addr\n");
		result = -1;
	}

	return(result);
}

int PR2000_SetAttrGpioPin(const int i2cFd, const uint8_t slvAddr, const _stAttrGpioPin *pstPr2000AttrGpioPin)
{
	int result = -1;
	_stPR2000_Reg stReg;
	uint8_t u8RegData;
	uint8_t u8RegMask;
	int gpioNum = 0;

	Print("%02x-Set gpio attribute register\n", slvAddr);

	/* set chip attribute */
	if(pstPr2000AttrGpioPin->i2cSlvAddr == slvAddr)
	{
		{    
			int j;
			PrintString("   [ENV] Gpio Attribute:\n");
			Print("    I2C SlvAddr7bit(0x%02X)\n", pstPr2000AttrGpioPin->i2cSlvAddr>>1);

			for(j = 0; j < 9; j++)
			{    
				Print("    gpio%d [iob:%d, ext_md:%d, mpp_md:%d, mpp_sel:%d, gpio0_irq_md:%d]\n", j COMMA
						pstPr2000AttrGpioPin->gpio[j].gpio_iob COMMA
						pstPr2000AttrGpioPin->gpio[j].gpio_ext_md COMMA
						pstPr2000AttrGpioPin->gpio[j].gpio_mpp_md COMMA
						pstPr2000AttrGpioPin->gpio[j].mpp_sel COMMA
						pstPr2000AttrGpioPin->gpio[j].gpio0_irq_md);
			}                    
		}            

		for(gpioNum = 0; gpioNum <= 8; gpioNum++)
		{
			Dbg("Set gpio num:%d\n", gpioNum);

			//gpio_iob;
			if(gpioNum == 8)
			{
				stReg.reg = 0x00A0;
				u8RegMask = 0x01;
				u8RegData = (pstPr2000AttrGpioPin->gpio[gpioNum].gpio_iob & 0x1)<<0;
				result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
			}
			else
			{
				stReg.reg = 0x00A1;
				u8RegMask = 0x01<<gpioNum;
				u8RegData = (pstPr2000AttrGpioPin->gpio[gpioNum].gpio_iob & 0x1)<<gpioNum;
				result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
			}
			//gpio_ext_md;
			if(gpioNum == 8)
			{
				stReg.reg = 0x00A4;
				u8RegMask = 0x01;
				u8RegData = (pstPr2000AttrGpioPin->gpio[gpioNum].gpio_ext_md & 0x1)<<0;
				result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
			}
			else
			{
				stReg.reg = 0x00A5;
				u8RegMask = 0x01<<gpioNum;
				u8RegData = (pstPr2000AttrGpioPin->gpio[gpioNum].gpio_ext_md & 0x1)<<gpioNum;
				result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
			}
			//gpio_mpp_md;
			if(gpioNum == 0)
			{
				stReg.reg = 0x00A6;
				u8RegMask = 0x08;
				u8RegData = (pstPr2000AttrGpioPin->gpio[gpioNum].gpio_mpp_md & 0x1)<<3;
				result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
			}
			else if(gpioNum == 1)
			{
				stReg.reg = 0x00A6;
				u8RegMask = 0x80;
				u8RegData = (pstPr2000AttrGpioPin->gpio[gpioNum].gpio_mpp_md & 0x1)<<7;
				result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
			}
			else if(gpioNum == 2)
			{
				stReg.reg = 0x00A7;
				u8RegMask = 0x08;
				u8RegData = (pstPr2000AttrGpioPin->gpio[gpioNum].gpio_mpp_md & 0x1)<<3;
				result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
			}
			else if(gpioNum == 3)
			{
				stReg.reg = 0x00A7;
				u8RegMask = 0x80;
				u8RegData = (pstPr2000AttrGpioPin->gpio[gpioNum].gpio_mpp_md & 0x1)<<7;
				result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
			}
			else if(gpioNum == 4)
			{
				stReg.reg = 0x00A8;
				u8RegMask = 0x08;
				u8RegData = (pstPr2000AttrGpioPin->gpio[gpioNum].gpio_mpp_md & 0x1)<<3;
				result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
			}
			//mpp_sel;
			if(gpioNum == 0)
			{
				stReg.reg = 0x00A6;
				u8RegMask = 0x03;
				u8RegData = (pstPr2000AttrGpioPin->gpio[gpioNum].mpp_sel & 0x3)<<0;
				result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
			}
			else if(gpioNum == 1)
			{
				stReg.reg = 0x00A6;
				u8RegMask = 0x30;
				u8RegData = (pstPr2000AttrGpioPin->gpio[gpioNum].mpp_sel & 0x3)<<4;
				result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
			}
			else if(gpioNum == 2)
			{
				stReg.reg = 0x00A7;
				u8RegMask = 0x03;
				u8RegData = (pstPr2000AttrGpioPin->gpio[gpioNum].mpp_sel & 0x3)<<0;
				result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
			}
			else if(gpioNum == 3)
			{
				stReg.reg = 0x00A7;
				u8RegMask = 0x30;
				u8RegData = (pstPr2000AttrGpioPin->gpio[gpioNum].mpp_sel & 0x3)<<4;
				result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
			}
			else if(gpioNum == 4)
			{
				stReg.reg = 0x00A8;
				u8RegMask = 0x03;
				u8RegData = (pstPr2000AttrGpioPin->gpio[gpioNum].mpp_sel & 0x3)<<0;
				result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
			}		
			//gpio0_irq_md;
			stReg.reg = 0x00A4;
			u8RegMask = 0x10;
			u8RegData = (pstPr2000AttrGpioPin->gpio[gpioNum].gpio0_irq_md & 0x1)<<4;
			result = PR2000_PageWriteMaskBit(i2cFd, slvAddr, stReg.b.page, stReg.b.addr, u8RegMask, u8RegData);
		}
	}
	else
	{
		ErrorString("Invalid i2c slave addr\n");
		result = -1;
	}

	return(result);
}




